<?php
/**
 * File:          KValidator
 * Description:   -
 * Author:        Kovac "Kovacou'" Alexandre (www.kovacou.fr)
 * Last Update:   22/04/2011
 */

   class KValidator {
      // #----------------------------------------------------------------
      //                        DECLARATION
      // #----------------------------------------------------------------
      const             POST     = 0,
                        GET      = 1,
                        COOKIE   = 2;
      
      protected         $uniqid,
                        $method,
                        $elements,
                        $error,
                        $sent,
                        $valid,
                        $values,
                        $uploads,
                        $vars,
                        $token,
                        $data,
                        $exec,
                        $pathFile;

      static protected  $dir,
                        $dirCache,
                        $dirModel,
                        $construct,
                        $declare = array(),
                        $replace,
                        $tokenInit;

      

      // #----------------------------------------------------------------
      //                            CORE
      // #----------------------------------------------------------------
      
      public function __construct ($uniqid, $values = null) {
         if (!isset (self::$construct)) {
            self::$dir = dirname(__FILE__);
            self::$dirCache = sprintf ("%s/Tmp/Cache/", self::$dir);
            self::$dirModel = sprintf ("%s/Tmp/Model/", self::$dir);

            if (!defined ("KV_DEBUG"))
               define ("KV_DEBUG", false);
            
            try {
               if (!defined ("KV_FILE"))
                  define ("KV_FILE", "ini");
               elseif (KV_FILE !== "yml" && KV_FILE !== "ini")
                  throw new Exception ("KValidator - La valeur de la constante KValidator_FILE est incorrecte. Le validateur ne peut continuer.");

               if (defined ("KV_CHARSET"))
                  $this->charset (KV_CHARSET);

               if (defined ("KV_CACHE")) {
                  self::$dirCache = KV_CACHE;

                  if (false === file_exists (self::$dirCache))
                     throw new Exception (sprintf("KValidator - Le dossier cache que vous avez indiqué n'existe pas. (%s)", self::$dirCache));
               }

               if (defined ("KV_MODEL")) {
                  self::$dirModel = KV_MODEL;

                  if (false === file_exists (self::$dirCache))
                     throw new Exception (sprintf("KValidator - Le dossier cache que vous avez indiqué n'existe pas. (%s)", self::$dirCache));
               }

               if (function_exists ("__autoload"))
                  spl_autoload_register ("__autoload");

               spl_autoload_register (array ("KValidator", "__autoexec"));

               if (false === class_exists("sfYaml"))
                  include_once sprintf("%s/Dependances/sfYaml/sfYaml.php", self::$dir);
            }
            catch (Exception $e) {
               exit ($e->getMessage());
            }
            
            self::$construct = true;
         }

         $this->elements = array ();
         $this->values   = array ();
         $this->vars     = array ();
         $this->uniqid   = trim ($uniqid);
         
         try {
            if (false === file_exists ($this->pathFile = self::$dirModel.$this->uniqid.".".KV_FILE))
               throw new Exception (sprintf("Le modèle <strong>%s</strong> n'existe pas. (%s)", $this->uniqid, $this->pathFile));
         }
         catch (Exception $e) {
            exit ($e->getMessage());
         }
         
         self::$declare[$this->uniqid] = $this;

         if (is_array ($values))
            $this->data = $values;
         elseif ($values === KValidator::POST)
            $this->data = $_POST;
         elseif ($values === KValidator::GET)
            $this->data = $_GET;
         elseif ($values === KValidator::COOKIE)
            $this->data = $_COOKIE;
         else
            $this->data = $_REQUEST;
      }


      public static function __autoexec ($class) {
         if (substr($class, 0, strlen(__CLASS__)) !== __CLASS__)
            return false;
         
         if (@include $class.".php")
            return true;
         
         $class = explode("_", $class);
         
         if (true === isset ($class[3]) && @include sprintf (self::$dir."/Parameter/%s/%s.php", $class[2], $class[3]))
            return true;
         elseif (true === isset ($class[2]) && @include sprintf (self::$dir."/Element/%s.php", $class[2]))
            return true;
         
         return false;
      }


      public function charset ($set) {
         if (!@mb_internal_encoding ($set))
            throw new Exception ("L'encodage <strong>{$set}</strong> n'est pas valide !");
            
         return $this;
      }
      
      
      public function token ($val) {
         if (true === $val)
            $this->_tokenInit();
         
         return $this;
      }
      
      
      public function sent () {
         if (false === isset ($this->sent))
            $this->sent = isset ($this->data[$this->uniqid]);

         return $this->sent;
      }


      public function valid () {
         try {
            if (true === $this->sent () && false === isset ($this->valid)) {
               
               if (true === isset ($this->token) && $this->token["current"] !== $this->getData("token")) {
                  $this->setError ("token", "Une erreur est survenue, merci de recommencer.");
                  return $this->valid = false;
               }
               
               if (false === isset($this->exec)) {
                  $Cache = New KValidatorCache(self::$dirCache, KValidatorCache::UPDATE, $this->uniqid, filemtime ($this->pathFile));
                  
                  if ($Cache->expire() === true) {                        
                     $Parser = New KValidatorParser (((KV_FILE === "yml") ? sfYaml::load($this->pathFile) : parse_ini_file ($this->pathFile, true)));
                     $Cache->written ($Parser->display());
                     unset ($Parser);
                  }

                  include $Cache->getPath();
                  $this->exec = true;
               }
               
               foreach ($this->elements as &$element)
                  $element->valid ();
               
               return ($this->valid = false === isset ($this->error));
            }
            
            return $this->valid;
         }
         Catch (Exception $e){
            exit ($e->getMessage());
         }
      }
      
      
      
      // #----------------------------------------------------------------
      //                            SETTERS
      // #----------------------------------------------------------------

      public function setVar ($key, $value) {
         if (true === is_array ($key))
            foreach ($key as $tmp_key => &$tmp_value)
               $this->setVar ($tmp_key, $tmp_value);
         else
            $this->vars[$key] = $value;

         return $this;
      }

      
      public function setToken ($current, $next = null) {
         $this->token (true)
              ->token = array (
                  "current" => $current,
                  "next"    => $next
              );
         
         return $this;
      }

      
      public function setValue ($name, $value) {
         $this->values[$name] = $value;
      }
      
      
      public function setError ($name, $value) {
         $this->error[$name] = $value;
      }

      
      public function setUpload ($name, $param) {
         $this->uploads[$name] = $param;
      }
      
      
      public function unsetVar ($key) {
         if (true === isset ($this->vars[$key]))
            unset ($this->vars[$key]);
      }


      public function unsetValue ($name) {
         if (true === isset ($this->values[$name]))
            unset ($this->values[$name]);
      }
      

      public function unsetError ($name) {
         if (true === isset ($this->error[$name]))
            unset ($this->error[$name]);
      }
      
      
      public function isSetData ($name) {
         return isset ($this->data[$name]);
      }
      
      
      public function isCheck ($name, $value) {
         return true === isset ($this->values[$name]) && true === in_array ($value, $this->values[$name]);
      }
      
      
      // #----------------------------------------------------------------
      //                            GETTERS
      // #----------------------------------------------------------------
      
      public function getValue ($name = null) {
         if (false === isset ($name))
            return $this->values;

         if (true === isset ($this->values[$name]))
            return $this->values[$name];
      }
      
      
      public function getVar ($key) {
         if (true === isset ($this->vars[$key]))
            return $this->vars[$key];
      }
      
      
      public function getToken () {
         return $this->token["next"];
      }
      

      public function getData ($name, $secure = true) {
         if (true === isset($this->data[$name]))
            if ($secure === true)
               if (true === is_array ($name))
                  return array_map ('htmlspecialchars', $this->data[$name]);
               else
                  return htmlspecialchars ($this->data[$name]);
            else
               return $this->data[$name];
      }
      

      public function getStr ($name = null) {
         if (false === isset ($name))
            return array_map("htmlspecialchars", $this->values);

         if (true === isset ($this->values[$name]) && false === is_array ($this->values[$name]))
            return htmlspecialchars($this->values[$name], ENT_QUOTES);
      }
      

      public function getFile ($name = null) {
         if (false === isset ($name))
            return $_FILES;
         elseif (isset ($_FILES[$name]))
            return $_FILES[$name];
      }
      
      
      public function getElements () {
         return $this->elements;
      }

 
      public function getElementsByName () {
         return array_keys ($this->elements);
      }


      public function getElementById ($id) {
         if (true === isset ($this->elements[$id]))
            return $this->elements[$id];
      }
      
 
      public function getError ($name = null) {
         if (true === isset ($name))
            if (isset ($this->error[$name])) return $this->error[$name];
            else return;
            
         return $this->error;
      }
      
      
      public function getUploads () {
         return $this->uploads;
      }
      
      
      
      // #----------------------------------------------------------------
      //                         PROTECTED
      // #----------------------------------------------------------------
      
      protected function _add ($element, $name) {
         return $this->elements[$name] = New $element ($name, $this->uniqid);
      }
      

      protected function _tokenInit () {
         if (true === isset (self::$tokenInit))
            return $this;
         
         $this->token = array(
             'current' => (isset($_SESSION["KV_TOKEN"])) ? $_SESSION["KV_TOKEN"] : null,
             'next'    => $_SESSION["KV_TOKEN"] = md5 (uniqid (mt_rand()))
         );
         
         self::$tokenInit = true;
         
         return $this;
      }
      
      
      
      // #----------------------------------------------------------------
      //                         STATIC
      // #----------------------------------------------------------------

      static public function load ($uniqid, $values = array()) {
         if (true === isset (self::$declare[$uniqid]))
            return self::$declare[$uniqid];
         
         return New KValidator ($uniqid, $values);
      }
      

      static public function parserReplace ($key, $str) {
         if (false === isset (self::$replace))
           self::$replace = sfYaml::load (self::$dir."/KValidator.yml");
         
         if (isset (self::$replace[$key]))
            return str_replace (array_keys (self::$replace[$key]), array_values (self::$replace[$key]), $str);
         
         return $str;
      }
   }
 
/**
 * End
 * Of
 * File
 */
?>